package org.javanum.number;

import static org.junit.Assert.assertEquals;
import static org.junit.Assume.assumeTrue;

/**
 * Copyright 2010 Scott Fines
 * <p/>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p/>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p/>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * <p/>
 * Author: Scott Fines
 * Date: Mar 7, 2010
 */
public class TestUtils {
    public static final double DELTA=Math.pow(10.0,-10);
    
    private TestUtils(){}

    public static void assumeNotComplexInfinity(Complex...numbers) {
        for(Complex z: numbers){
            assumeTrue(!Complex.isInfinite(z));
        }
    }

    public static void assumeNotComplexInfinity(
                                    PolarComplex...numbers) {
        for(PolarComplex z: numbers){
            assumeTrue(!PolarComplex.isInfinite(z));
        }
    }

    
    public static void assumeNotRealInfinity(Real...reals){
        for(Real r:reals){
            assumeTrue(!Real.isInfinite(r));
        }
    }

    public static void assumeNotNaN(Complex... numbers) {
        for(Complex z:numbers)
            assumeTrue(!Complex.isNaN(z));
    }
    public static void assumeNotNaN(PolarComplex... numbers) {
        for(PolarComplex z:numbers)
            assumeTrue(!PolarComplex.isNaN(z));
    }

    public static void assumeNotNaN(Real...reals){
        for(Real r:reals){
            assumeTrue(!Real.isNaN(r));
        }
    }

    public static void assumeNotZero(Complex...numbers){
        for(Complex z:numbers){
            assumeTrue(!Complex.ZERO.equals(z));
        }
    }
    public static void assumeNotZero(PolarComplex...numbers){
        for(PolarComplex z:numbers){
            assumeTrue(z.magnitude!=0);
        }
    }

    public static void assumeNotZero(Real...reals){
        for(Real r:reals){
            assumeTrue(!Real.ZERO.equals(r));
        }
    }

    public static void assumeReasonable(Complex...numbers){
        assumeNotComplexInfinity(numbers);
        assumeNotNaN(numbers);
    }

    public static void assumeReasonable(Real...reals){
        assumeNotRealInfinity(reals);
        assumeNotNaN(reals);
    }


    public static <T,K> String format(
            String errorMsg,String expectedLabel,T expected,
                            String actualLabel,K actual){
        return String.format(errorMsg+"%n"+
                expectedLabel+"=%1$s%n" +
                actualLabel+"=%2$s",expected,actual);
    }

    public static void assertComplexEquality(String errorMsg,
                                             Complex expected,
                                             Complex actual,
                                             double delta){
        assertEquals(String.format(errorMsg+
                    "--real parts do not match%n"+
                    "z=%1$s%n" +
                    "w=%2$s",expected,actual),
                expected.real,actual.real,delta);
        assertEquals(String.format(errorMsg+
                    "--imaginary parts do not match%n"+
                    "z=%1$s%n" +
                    "w=%2$s",expected,actual),
                expected.imaginary,actual.imaginary,delta);

    }
    public static void assertComplexEquality(String errorMsg,
                                             PolarComplex expected,
                                             PolarComplex actual,
                                             double delta){
        assertMagnitudeEquals(errorMsg,expected,actual,delta);
        assertAngleEquals(errorMsg,expected,actual,delta);

    }

    public static void assertMagnitudeEquals(String errorMsg,
                                             PolarComplex expected,
                                             PolarComplex actual,
                                             double delta){
        assertEquals(String.format(errorMsg+
                    "--magnitudes do not match%n"+
                    "z=%1$s%n" +
                    "w=%2$s",expected,actual),
                expected.magnitude,actual.magnitude,delta);

    }

    public static void assertAngleEquals(String errorMsg,
                                         PolarComplex expected,
                                         PolarComplex actual,
                                         double delta){
        assertEquals(String.format(errorMsg+
                    "--angles do not match%n"+
                    "z=%1$s%n" +
                    "w=%2$s",expected,actual),
                expected.angle,actual.angle,delta);
    }

    public static void assumeMagnitudeNotZero(PolarComplex...p){
    	for(PolarComplex complex:p){
    		assumeTrue(Double.compare(complex.magnitude,0)!=0);
    	}
    }
    
    public static boolean isEqualToAccuracy(Complex z,Complex w, double delta){
    	if(Math.abs(z.real-w.real)>=delta)
    		return false;
    	
    	return Math.abs(z.imaginary-w.imaginary)<delta;
    }
    
    public static boolean 
    			isEqualToAccuracy(PolarComplex z,PolarComplex w, double delta){
    	if(Math.abs(z.magnitude-w.magnitude)>=delta)
    		return false;
    	
    	return Math.abs(z.magnitude-w.magnitude)<delta;
    }
}
